package cn.wolfcode.wolf2w.strategy.service.impl;

import cn.wolfcode.wolf2w.common.redis.service.RedisService;
import cn.wolfcode.wolf2w.common.redis.util.RedisKeys;
import cn.wolfcode.wolf2w.strategy.entity.*;
import cn.wolfcode.wolf2w.strategy.mapper.StrategyCatalogMapper;
import cn.wolfcode.wolf2w.strategy.mapper.StrategyContentMapper;
import cn.wolfcode.wolf2w.strategy.mapper.StrategyMapper;
import cn.wolfcode.wolf2w.strategy.mapper.StrategyThemeMapper;
import cn.wolfcode.wolf2w.strategy.query.StrategyQuery;
import cn.wolfcode.wolf2w.strategy.service.IStrategyService;
import cn.wolfcode.wolf2w.strategy.util.DateUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 攻略Service业务层处理
 * 
 * @author libai
 * @date 2024-07-24
 */
@Service
@Transactional
public class StrategyServiceImpl extends ServiceImpl<StrategyMapper,Strategy> implements IStrategyService {

    @Autowired
    private StrategyContentMapper strategyContentMapper;

    @Autowired
    private StrategyCatalogMapper strategyCatalogMapper;

    @Autowired
    private StrategyThemeMapper strategyThemeMapper;

    @Autowired
    private StrategyMapper strategyMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public IPage<Strategy> queryPage(StrategyQuery qo) {
        IPage<Strategy> page = new Page<>(qo.getCurrentPage(), qo.getPageSize());
        return lambdaQuery()
                .eq(qo.getThemeId() != null,Strategy::getThemeId,qo.getThemeId())
                .eq(qo.getCatalogId() != null,Strategy::getCatalogId,qo.getCatalogId())
                .like(!StringUtils.isBlank(qo.getTitle()),Strategy::getTitle,qo.getTitle())
                .eq(qo.getIsabroad()!=null, Strategy::getIsabroad, qo.getIsabroad())
                .eq(qo.getState()!=null, Strategy::getState, qo.getState())
                .eq(qo.getRefid() != null &&(qo.getType() == 1 || qo.getType()==2)
                            ,Strategy::getDestId,qo.getRefid())
                .eq(qo.getRefid() != null &&qo.getType() == 3
                             ,Strategy::getThemeId,qo.getRefid())
                .page(page);
    }

    @Override
    public List<Strategy> queryViewTop3ByDestId(Long destId) {
        List<Strategy> list = lambdaQuery().eq(Strategy::getDestId, destId)
                .eq(Strategy::getState, 1)
                .orderByDesc(Strategy::getViewnum)
                .last("limit 3").list();
        return list;
    }

    @Override
    public StrategyContent getContent(Long id) {
        StrategyContent strategyContent = strategyContentMapper.selectById(id);
        return strategyContent;
    }

    @Override
    public boolean strategySave(Strategy strategy) {
        StrategyCatalog catalog = strategyCatalogMapper.selectById(strategy.getCatalogId());
        strategy.setDestId(catalog.getDestId());
        strategy.setDestName(catalog.getDestName());
        strategy.setCatalogName(catalog.getName());
        StrategyTheme theme = strategyThemeMapper.selectById(strategy.getThemeId());
        strategy.setThemeName(theme.getName());
        strategy.setCreateTime(new Date());

//        strategy.setIsabroad(0l);
        strategy.setViewnum(0l);
        strategy.setReplynum(0l);
        strategy.setFavornum(0l);
        strategy.setSharenum(0l);
        strategy.setThumbsupnum(0l);
        save(strategy);
        StrategyContent strategyContent = new StrategyContent();
        strategyContent.setId(strategy.getId());
        strategyContent.setContent(strategy.getContent().getContent());
        strategyContentMapper.insert(strategyContent);

        //TODO : 发消息到MQ 2024/08/12
        String message = JSON.toJSONString(strategy);
        //redis操作
        String key = RedisKeys.ES_DATA.join("key");
        redisTemplate.opsForZSet().add(key,message,System.currentTimeMillis());
        amqpTemplate.convertAndSend("esTopicExchange","esKey", message);



        return true;
    }

    @Override
    public Strategy queryDetailById(Long id) {
        Strategy strategy = strategyMapper.selectById(id);
        StrategyContent strategyContent = strategyContentMapper.selectById(id);
        strategy.setContent(strategyContent);
        return strategy;
    }

    //抽取方法
    private String strategyHashInit(Long sid){
        String key = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        Boolean b = redisService.hasKey(key);
        if (!b) {
            Strategy strategy = strategyMapper.selectById(sid);
//            Map<String, Object> map = new HashMap<>();
//            map.put("viewnum",Integer.valueOf(strategy.getViewnum().toString()));
//            map.put("sharenum",Integer.valueOf(strategy.getSharenum().toString()));
//            map.put("favornum",Integer.valueOf(strategy.getFavornum().toString()));
//            map.put("replynum",Integer.valueOf(strategy.getReplynum().toString()));
//            map.put("thumbsupnum",Integer.valueOf(strategy.getThumbsupnum().toString()));
//            map.put("id",strategy.getId());
            Map<String, Object> map = strategyMap(strategy);
            redisService.setCacheMap(key,map);
        }
        return key;
    }


    @Override
    public Map<String, Object> viewnumIncr(Long sid) {
        //调用抽取方法
        String key = strategyHashInit(sid);
        redisService.incrementCacheMapValue(key,"viewnum",1);
        Map<String, Object> result = redisService.getCacheMap(key);
        return result;
    }

    @Override
    public Map<String,Object>incrCommentCount(Long sid) {
        String key = strategyHashInit(sid);
        redisService.incrementCacheMapValue(key,"replynum",1);
        Map<String, Object> map = redisService.getCacheMap(key);
        return map;
    }

    @Override
    public void statisHashDataPersistence() {
        //获取redis中所有strategy_statis_hash的key
        Collection<String> keys = redisService.keys(RedisKeys.STRATEGY_STATIS_HASH.join("*"));
        if (keys != null &&keys.size()>0){
            //如果找到了
            for (String key : keys) {
                Map<String, Object> map = redisService.getCacheMap(key);
                UpdateWrapper<Strategy> uw = new UpdateWrapper<>();
                uw.eq("id",map.get("id"));
                uw.set("viewnum", map.get("viewnum"));
                uw.set("sharenum", map.get("sharenum"));
                uw.set("replynum", map.get("replynum"));
                uw.set("favornum", map.get("favornum"));
                uw.set("thumbsupnum", map.get("thumbsupnum"));
                strategyMapper.update(null, uw);
            }
        }
    }
    //抽取的方法
    private Map<String,Object> strategyMap(Strategy strategy){
        //不存在redis中,需要写入redis
        Map<String, Object> map = new HashMap<>();
        map.put("viewnum",Integer.valueOf(strategy.getViewnum().toString()));
        map.put("sharenum",Integer.valueOf(strategy.getSharenum().toString()));
        map.put("favornum",Integer.valueOf(strategy.getFavornum().toString()));
        map.put("replynum",Integer.valueOf(strategy.getReplynum().toString()));
        map.put("thumbsupnum",Integer.valueOf(strategy.getThumbsupnum().toString()));
        map.put("id",strategy.getId());
        return map;
    }


    @Override
    public void statisHashInit() {
        List<Strategy> strategies = strategyMapper.selectList(null);
        for (Strategy strategy : strategies) {
            String key = RedisKeys.STRATEGY_STATIS_HASH.join(strategy.getId().toString());
            if (redisService.hasKey(key)){
                continue;
            }
            //抽取方法
            Map<String, Object> map = strategyMap(strategy);
            redisService.setCacheMap(key,map);
        }
    }

    @Override
    public Map<String, Object> favor(Long sid, Long uid) {

        String key = RedisKeys.USER_STRATEGY_FAVOR.join(uid.toString());
        Boolean b = redisService.hasKey(key);
        if (!b) {
            //当前用户未收藏过任何文章
            Set<Long> sidSet = new HashSet<>();
            sidSet.add(-1l);
            redisService.setCacheSet(key, sidSet);
        }
        String statisKey = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        boolean flg = redisService.isCacheSetContains(key, sid);

        if (flg){
            //当前用户收藏过该文章
            redisService.incrementCacheMapValue(statisKey,"favornum",-1);
            redisService.deleteCacheSetValue(key,sid);
        }else {
            redisService.incrementCacheMapValue(statisKey,"favornum",1);
            redisService.addCacheSetValue(key,sid);
        }
        Map<String, Object> map = redisService.getCacheMap(statisKey);
        map.put("result",!flg);
        return map;
    }

    @Override
    public boolean isUserFavor(Long sid, Long uid) {
        String key = RedisKeys.USER_STRATEGY_FAVOR.join(uid.toString());
        Boolean b = redisService.hasKey(key);
        if (!b) {
            //当前用户未收藏过任何文章
            Set<Long> sidSet = new HashSet<>();
            sidSet.add(-1l);
            redisService.setCacheSet(key, sidSet);
        }
        boolean flg = redisService.isCacheSetContains(key, sid);
        return flg;
    }

    @Override
    public Map<String, Object> thumbsup(Long sid, Long uid) {
        String key = RedisKeys.STRATEGY_THUMBSUP.join(uid.toString(), sid.toString());
        Date now = new Date();
        Date endDate = DateUtil.getEndDate(now);
        long time = DateUtil.getDateBetween(now, endDate);
        redisService.setnxacheObject(key,0,time, TimeUnit.SECONDS);

        Long count = redisService.incrCacheObject(key);

//        Map<String, Object> map = new HashMap<>();
//        Map<String, Object> map = redisService.getCacheMap(key);
        boolean flg = true;
        String statisKey = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        if (count >5) {
            //今天不能再继续点赞
          flg = false;
        }else {
            //可以点赞,点赞数+1
            redisService.incrementCacheMapValue(statisKey,"thumbsupnum",1);
        }
        Map<String, Object> map = redisService.getCacheMap(statisKey);
        map.put("result", flg);
        return map;
    }
}
